package com.wx.house.common.config;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

/**
 * @author yxs
 */
@Aspect
@Configuration
@ConditionalOnProperty(prefix = "common", name = "transaction", havingValue = "true")
public class TransactionAdviceConfig {

private static final String AOP_POINTCUT_EXPRESSION = "execution(* *..*Service*.*(..))";
@Transactional
@Bean
public TransactionInterceptor txAdvice(
		@Qualifier("transactionManager") PlatformTransactionManager transactionManager) {
	
	DefaultTransactionAttribute txAttr_REQUIRED = new DefaultTransactionAttribute();
	txAttr_REQUIRED.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
	
	DefaultTransactionAttribute txAttr_REQUIRED_READONLY = new DefaultTransactionAttribute();
	txAttr_REQUIRED_READONLY.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
	txAttr_REQUIRED_READONLY.setReadOnly(true);
	
	NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
	source.addTransactionalMethod("add*", txAttr_REQUIRED);
	source.addTransactionalMethod("save*", txAttr_REQUIRED);
	source.addTransactionalMethod("insert*", txAttr_REQUIRED);
	source.addTransactionalMethod("create*", txAttr_REQUIRED);
	source.addTransactionalMethod("register*", txAttr_REQUIRED);
	
	//逻辑删除
	source.addTransactionalMethod("logicDelete*", txAttr_REQUIRED);
	source.addTransactionalMethod("delete*", txAttr_REQUIRED);
	source.addTransactionalMethod("remove*", txAttr_REQUIRED);
	
	source.addTransactionalMethod("update*", txAttr_REQUIRED);
	source.addTransactionalMethod("change*", txAttr_REQUIRED);
	
	source.addTransactionalMethod("exec*", txAttr_REQUIRED);
	source.addTransactionalMethod("set*", txAttr_REQUIRED);
	
	//检查
	source.addTransactionalMethod("check*", txAttr_REQUIRED_READONLY);
	source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
	source.addTransactionalMethod("select*", txAttr_REQUIRED_READONLY);
	source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
	source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
	source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
	source.addTransactionalMethod("is*", txAttr_REQUIRED_READONLY);
	source.addTransactionalMethod("login*", txAttr_REQUIRED_READONLY);
	return new TransactionInterceptor(transactionManager, source);
}

@Bean
public Advisor txAdviceAdvisor(@Qualifier("txAdvice") TransactionInterceptor transactionInterceptor) {
	AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
	pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
	return new DefaultPointcutAdvisor(pointcut, transactionInterceptor);
}
}
